package Server;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ConcurrentLinkedQueue;

import Game.Game;
import MessageComponent.MessageThroughPipe;

public class Server {

	public static final int PORT = 8080;

	private ObjectInputStream in;
	private ObjectOutputStream out;
	private Socket socket;
	private ServerSocket serverSocket;
	private int id;

	// private ArrayList<DealWithClient> clientsArray;
	private ConcurrentLinkedQueue<DealWithClient> clientsArray;
	private boolean running;

	private Game game;
	private ServerStartupGUI serverStartupGUI;

	public Server() {
		// clientsArray = new ArrayList<DealWithClient>();
		clientsArray = new ConcurrentLinkedQueue<DealWithClient>();
		id = 0;
		game = new Game();
		serverStartupGUI = new ServerStartupGUI(this);
	}

	public void runServer() {
		game.informationFromServer(
				Integer.parseInt(serverStartupGUI.getNumPlayerField().getText()),
				Integer.parseInt(serverStartupGUI.getNumBarriersField()
						.getText()),
				Integer.parseInt(serverStartupGUI.getNumItemsField().getText()),
				Integer.parseInt(serverStartupGUI.getNumColumnsField()
						.getText()), Integer.parseInt(serverStartupGUI
						.getNumLinesField().getText()));
		running = true;
		try {
			serverSocket = new ServerSocket(PORT);
			while (running) {
				if (id < Integer.parseInt(serverStartupGUI.getNumPlayerField()
						.getText())) {
					System.out.println("Server is Waiting for Connections...");
					socket = serverSocket.accept();
					System.out.println("Connection Accepted");
					if (!running) {
						break;
					}
					doConnections();
					id++;
					DealWithClient clientToDeal = new DealWithClient(this, id,
							in, out, socket, game);
					clientsArray.add(clientToDeal);
					clientToDeal.start();
				} else {
				}
			}
			for (DealWithClient dwc : clientsArray) {
				dwc.getIn().close();
				dwc.getOut().close();
				dwc.getSocket().close();
			}
			serverSocket.close();
			running = false;
		} catch (IOException e) {
			System.err.println("ServerSocket done Wrong: " + e.getMessage());
			running = false;
			System.exit(1);
		}
	}

	private void doConnections() {
		try {
			in = new ObjectInputStream(socket.getInputStream());
			out = new ObjectOutputStream(socket.getOutputStream());
		} catch (IOException e) {
			System.err.println("Connections done Wrong: " + e.getMessage());
			running = false;
		}
	}

	public synchronized void broadcast(MessageThroughPipe mtp) {
		try {
			for (DealWithClient handler : clientsArray) {
				handler.getOut().writeObject(mtp);
				handler.getOut().flush();
			}
		} catch (IOException e) {
			System.err.println("Broadcast Exception: " + e.getMessage());
		}
	}

	public void removeClient(int id) {
		for (DealWithClient cc : clientsArray) {
			if (cc.getConnectionId() == id) {
				clientsArray.remove(cc);
			}
		}
		if (clientsArray.isEmpty()) {
			System.out.println("serverSocket Closed");
			try {
				serverSocket.close();
				socket.close();
				System.exit(0);
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	public static void main(String[] args) {
		new Server();
	}
}
